package com.gec.it.service.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gec.it.service.ApproveService;
@Service
public class ApproveServiceImpl implements ApproveService{
	@Autowired
	private RepositoryService rpService;
	@Autowired
	private RuntimeService runService;
	@Autowired
	private HistoryService hisService;// 负责历史记录的查询的service
	@Autowired
	private TaskService taskService;

	//根据业务id找批注
	public List<Comment> findCommentByBizkey(String processDefineKey,String bizkey) {
		//找到bizkey对应的流程实例id
		HistoricProcessInstance procIns= hisService
				.createHistoricProcessInstanceQuery()
				.processDefinitionKey(processDefineKey)//流程图的key
				.processInstanceBusinessKey(bizkey)//业务id
				.singleResult();
		return this.findComment(procIns.getId());
	}

	@Override
	//根据流程id查找批注
	public List<Comment> findComment(String procInsId){
		List<Comment>list =taskService.getProcessInstanceComments(procInsId);
		return list;
	}
	@Override
	//根据任务查找批注
	public List<Comment> findCommentByTask(Task task){


		return findComment(task.getParentTaskId());
	}
	@Override
	//根据任id务查找批注
	public List<Comment> findCommentByTask(String taskId){

		return findCommentByTask(this.findTaskById(taskId));
	}

	@Override
	public List<Comment> findCommentByBizkey(String bizkey) {
		HistoricProcessInstance proc = hisService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(bizkey).singleResult();
		return this.findComment(proc.getId());
	}


	// 结束一个任务，包括领取组任务，添加批注信息，结束任务，返回下一个任务
	@Override
	public Task saveSubmitTask(String taskId, String currentuser, String message, Map<String, Object> variables) {

		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		if (task.getAssignee() == null || task.getAssignee().isEmpty())// 如果是组任务，则assignee属性为空
			this.Group2User(taskId, currentuser);// 如果是组任务，当前用户领取这个任务，则设置当前用户为操作人

		String processInstanceId = task.getProcessInstanceId();
		// 记录批注信息在特定的表
		if (message != null && !message.isEmpty()) {
			Authentication.setAuthenticatedUserId(currentuser);// 录入批注人是谁 2_王武
			taskService.addComment(taskId, processInstanceId, message);
		}
		// 结束任务
		taskService.complete(taskId, variables);// 传入相应的变量，指引下一步的方向，或者是供后续任务使用

		// 查询下一个任务是谁(可能你需要知道下一个任务的名称...)
		ProcessInstance pi = runService.createProcessInstanceQuery().processInstanceId(processInstanceId)
				.singleResult();
		if (pi == null)
			return null;
		return this.findTaskByProcessInstId(pi.getId());
	}

	// 根据id查找task对象
	@Override
	public Task findTaskById(String taskid) {
		return taskService.createTaskQuery().taskId(taskid).singleResult();
	}

	// 返回流程出口连线的名称，我们控制按钮的名称
	@Override
	public List<String> findOutComeListByTaskId(String taskId) {
		// 返回存放连线的名称集合
		List<String> list = new ArrayList<String>();
		// 1:使用任务ID，查询任务对象
		Task task = taskService.createTaskQuery()//
				.taskId(taskId)// 使用任务ID查询
				.singleResult();
		// 2：获取流程定义ID
		String processDefinitionId = task.getProcessDefinitionId();
		// 3：查询ProcessDefinitionEntiy对象
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) rpService
				.getProcessDefinition(processDefinitionId);
		// 使用任务对象Task获取流程实例ID
		String processInstanceId = task.getProcessInstanceId();
		// 使用流程实例ID，查询正在执行的执行对象表，返回流程实例对象
		ProcessInstance pi = runService.createProcessInstanceQuery()//
				.processInstanceId(processInstanceId)// 使用流程实例ID查询
				.singleResult();
		// 获取当前活动的id
		String activityId = pi.getActivityId();
		// 4：获取当前的活动
		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
		// 5：获取当前活动完成之后连线的名称
		List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
		if (pvmList != null && pvmList.size() > 0) {
			for (PvmTransition pvm : pvmList) {
				String name = (String) pvm.getProperty("name");
				if (StringUtils.isNotBlank(name)) {
					list.add(name);
				} else {
					list.add("默认提交");
				}
			}
		}
		return list;
	}

	// 根据任务查询组任务成员
	@Override
	public List<String> findGroupUsersKey(String taskid) {
		List<IdentityLink> groupLinks = taskService.getIdentityLinksForTask(taskid);
		// 在这里加工更好
		List<String> list = new ArrayList<>();
		for (IdentityLink lk : groupLinks) {
			list.add(lk.getUserId());
		}
		return list;
	}

	// 根据任务查询组任务成员
	@Override
	public List<IdentityLink> findGroupUsers(String taskid) {
		List<IdentityLink> list = taskService.getIdentityLinksForTask(taskid);
		return list;
	}

	@Override
	public String findBizkeyByTask(Task t) {
		ProcessInstance p = runService.createProcessInstanceQuery().processInstanceId(t.getProcessInstanceId())
				.singleResult();
		return p.getBusinessKey();
	}

	// 查找个人用户应该处理的任务(包含各种流程图的)
	@Override
	public List<Task> findTaskListByName(String userkey) {
		return taskService.createTaskQuery()// 创建对act_ru_task的查询
				.taskAssignee(userkey)// 根据assignee这列筛选
				.orderByTaskCreateTime()// 按创建事件排序
				.asc()// 正序，越早的在上面
				.list();// 返回集合
	}

	// 查找个人用户应该处理的任务(指定流程图的)
	@Override
	public List<Task> findTaskListByName(String processDefineKey, String userkey) {
		return taskService.createTaskQuery()// 创建对act_ru_task的查询
				.processDefinitionKey(processDefineKey)// 根据流程图的名字筛选
				.taskAssignee(userkey)// 根据assignee这列筛选
				.orderByTaskCreateTime()// 按创建事件排序
				.asc()// 正序，越早的在上面
				.list();// 返回集合
	}

	// 查找组用户应该处理的任务(不区分流程图的)
	@Override
	public List<Task> findGroupTaskListByName(String userkey) {
		return taskService.createTaskQuery()// 创建对act_ru_task的查询
				.taskCandidateUser(userkey)// 根据组任务人筛选
				.orderByTaskCreateTime()// 按创建事件排序
				.asc()// 正序，越早的在上面
				.list();// 返回集合
	}


	// 查找组用户应该处理的任务(指定流程图的)
	@Override
	public List<Task> findGroupTaskListByName(String processDefineKey, String userkey) {
		return taskService.createTaskQuery()// 创建对act_ru_task的查询
				.processDefinitionKey(processDefineKey)// 根据流程图的名字筛选
				.taskCandidateUser(userkey)// 根据组任务人筛选
				.orderByTaskCreateTime()// 按创建事件排序
				.asc()// 正序，越早的在上面
				.list();// 返回集合
	}

	/**
	 * 二：查看当前活动，获取当期活动对应的坐标x,y,width,height，将4个值存放到Map<String,Object>中
	 * map集合的key：表示坐标x,y,width,height map集合的value：表示坐标对应的值
	 */
	@Override
	public List<Map<String, Object>> findCoordingByBizkey(String processDefineKey, String bizkey) {
		// 存放坐标
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		ProcessInstance pi = this.findProcessInstanceByBizkey(processDefineKey, bizkey);
		if (pi == null)
			return list;
		List<Execution> exlist = this.runService.createExecutionQuery().processDefinitionKey(processDefineKey)
				.processInstanceBusinessKey(bizkey).list();
		if (exlist.size() == 0)
			return list;
		// 获取流程定义的ID
		String processDefinitionId = pi.getProcessDefinitionId();
		// 获取流程定义的实体对象（对应.bpmn文件中的数据）
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) rpService
				.getProcessDefinition(processDefinitionId);
		// 使用流程实例ID，查询正在执行的执行对象表，获取当前活动对应的流程实例对象
		// 获取当前活动的ID
		for (Execution ex : exlist) {
			Map<String, Object> map = new HashMap<String, Object>();
			String activityId = ex.getActivityId();
			// 获取当前活动对象
			ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);// 活动ID
			// 获取坐标
			map.put("x", activityImpl.getX());
			map.put("y", activityImpl.getY());
			map.put("width", activityImpl.getWidth());
			map.put("height", activityImpl.getHeight());
			list.add(map);
		}
		return list;
	}

	// 查找流程图信息用于显示图片（根据发布ID和图片名称）
	@Override
	public InputStream findImageInputStream(String deploymentId, String imageName) {
		return rpService.getResourceAsStream(deploymentId, imageName);
	}

	// 根据流程key值和绑定的业务key值，查找流程图，用于显示流程图
	@Override
	public InputStream findImageInputStreamByBizkey(String processDefineKey, String bizkey) {
		ProcessInstance pi = this.findProcessInstanceByBizkey(processDefineKey, bizkey);
		if (pi == null)
			return null;
		String deploymentId = pi.getDeploymentId();
		String imageName = this.rpService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult()
				.getDiagramResourceName();
		return this.findImageInputStream(deploymentId, imageName);
	}

	// 根据业务id找到是否有开启的流程
	public HistoricProcessInstance findHisProcByBizkey(String prockey, String bizkey) {// baoxiao
		// 1
		// 根据"baoxiao"获取 流程图id
		// String
		// procdef_id=rpService.createProcessDefinitionQuery().processDefinitionKey(prockey).latestVersion().singleResult().getId();//baoxiao:3:5004
		HistoricProcessInstance hproc = hisService// 负责历史记录的查询的service
				.createHistoricProcessInstanceQuery()// 准备查询act_hi_procinst表
				.processDefinitionKey(prockey)// 根据key查(有可能内部会join表)
				.processInstanceBusinessKey(bizkey)// 根据业务id查
				.singleResult();// 返回单个值
		return hproc;
	}

	// 开启流程
	@Override
	public ProcessInstance startWorkflow(String prockey, int bizkey, Map<String, Object> map) {
		ProcessInstance proc = runService.startProcessInstanceByKey(prockey, bizkey + "", map);
		return proc;
	}

	@Override
	public void deploy(String name, InputStream input) {
		ZipInputStream zipInputStream = new ZipInputStream(input);
		rpService.createDeployment().name(name).addZipInputStream(zipInputStream).deploy();
	}

	@Override
	public List<Deployment> findDeploys() {
		List<Deployment> list = rpService.createDeploymentQuery().orderByDeploymenTime().desc().list();
		return list;
	}
	@Override
	public void removeDeploy(String id) {
		rpService.deleteDeployment(id);
	}

	// 根据业务key和流程的key来查找实例（因为业务key的值可能重复，可能是不同表相同的id)
	@Override
	public ProcessInstance findProcessInstanceByBizkey(String processDefineKey, String bizkey) {
		ProcessInstance pi = this.runService.createProcessInstanceQuery().processDefinitionKey(processDefineKey)
				.processInstanceBusinessKey(bizkey).singleResult();
		return pi;
	}

	// 根据流程实例id查找当前正在执行的任务
	@Override
	public Task findTaskByProcessInstId(String processInstid) {
		Task task = taskService.createTaskQuery()//
				.processInstanceId(processInstid).singleResult();
		return task;
	}

	// 领取任务，将组任务领取为个人任务
	@Override
	public void Group2User(String taskid, String currentuser) {
		if (isGroupUser(taskid))// 如果是组任务
			this.taskService.claim(taskid, currentuser);// 则领取这个任务
	}
	// 根据任务id判断是否组任务
	@Override
	public boolean isGroupUser(String taskId) {
		return this.isGroupUser(this.findTaskById(taskId));
	}

	// 根据任务对象判断是否组任务
	@Override
	public boolean isGroupUser(Task task) {
		return task.getAssignee() == null;// 如果assignee为空则应该为组任务(或者是你的疏忽)
	}




}
